#!/bin/bash
# node-reinstall
# credit: http://stackoverflow.com/a/11178106/2083544

## program version
VERSION="0.0.17"

## path prefix
PREFIX="${PREFIX:-/usr/local}"

## version control systems
USE_NAVE=0
USE_NVM=1

# use --force to bypass user confirmation
FORCE=0

## default node version
DEFAULT_NODE_VERSION="5"

## user-specified node version to install
DESIRED_NODE_VERSION=

## node version to install
NODE_VERSION=

usage () {
  printf "%s\n" "node-reinstall"
  printf "\t%s\n" "completely re-installs Node & NPM and any global node modules."
  printf "\t%s\n" "It re-installs Node using NVM or Nave"
  printf "\n"
  printf "%s\t%s\n" "Usage:" "node-reinstall [--nave|--nvm|--nvm-latest] [-h|--help] [-v|--version] [NODE_VERSION]"
  printf "\n"
  printf "%s\n" "Commands:"
  printf "\n"
  printf "\t%s\t\t\t%s\n" "node-reinstall" "re-install node and npm using nvm"
  printf "\t%s %s\t%s\n" "node-reinstall" "[-h|--help]" "show help"
  printf "\t%s %s\t%s\n" "node-reinstall" "[-v|--version]" "show the node-reinstall version number"
  printf "\t%s %s\t%s\n" "node-reinstall" "[-f|--force]" "installs defaults without user confirmation"
  printf "\t%s %s\t\t%s\n" "node-reinstall" "--nave" "re-install using nave"
  printf "\t%s %s\t\t%s\n" "node-reinstall" "--nvm" "re-install using stable nvm - the default"
  printf "\t%s %s\t%s\n" "node-reinstall" "--nvm-latest" "re-install using latest nvm - creationix/nvm:master"
  printf "\t%s %s\t\t%s\n" "node-reinstall" "0.12" "specify a default node version - currently ${NODE_VERSION}"
  printf "\n"
}

## parse opts
{

  for opt in ${@}; do
    case $opt in
      --help|-h)
        usage
        exit
        ;;

      --version|-v)
        echo ${VERSION}
        exit
        ;;

      --force|-f)
        FORCE=1
        ;;

      --nave)
        USE_NAVE=1
        USE_NVM=0
        ;;

      --nvm)
        USE_NVM=1
        USE_NAVE=0
        ;;

      --nvm-latest)
        USE_NVM=1
        USE_NAVE=0
        STABLE=master
        ;;

      *)
        if [ "-" == "${opt:0:1}" ]; then
          echo >&2 "error: Unknown option \`$opt'"
          usage >&2
          exit 1
        fi

        DESIRED_NODE_VERSION="${opt}"
    esac
  done

}

confirm ()
{
  if [[ $FORCE == 0 ]]; then
    echo ""
    echo "Would you like to continue running node-reinstall?"
    echo ""
    select yn in "Yes" "No"; do
          case $yn in
              Yes ) break;;
              No ) exit;;
          esac
    done
  fi
}

# get sudo
sudo -v

# if node is installed, get the installed version
INSTALLED_NODE_VERSION=$(node --version 2> /dev/null)

if [[ ! -z $DESIRED_NODE_VERSION ]]; then
  NODE_VERSION=$DESIRED_NODE_VERSION
elif [[ ! -z $INSTALLED_NODE_VERSION ]]; then
  NODE_VERSION=$INSTALLED_NODE_VERSION
else
  NODE_VERSION=$DEFAULT_NODE_VERSION
fi

# confirm re-installation only if node already exists
if [[ ! -z $INSTALLED_NODE_VERSION ]]; then
  echo "Found Node.js version $INSTALLED_NODE_VERSION already installed."
  echo "If you continue now, we will replace it with Node.js version $NODE_VERSION"
  confirm
fi

# check to see if npm is installed
IS_NPM_MISSING=$(which npm)
if [[ -z $IS_NPM_MISSING ]]; then
  echo "Installing Node, npm."
else
  echo "Completely reinstalling Node, npm."
  # get list of global npm modules to reinstall
  # omit the lib directory listing
  GLOBAL_MODULES=`npm -g list --depth 0 --parseable | xargs basename | sed -E 's/^(lib|npm)$//g'`
  if [[ -n $GLOBAL_MODULES ]]; then
    echo "Will reinstall these global npm modules:"
    echo $GLOBAL_MODULES
  else
    echo "===== ALERT! ====="
    echo "The script did not find any global node modules (npm -g list)"
    echo "If you are sure you installed global node modules"
    echo "(by running npm install -g some-module), you might want to stop "
    echo "here and locate those, because they won't be re-installed,"
    echo "and since we'll be deleting all the possible install paths "
    echo "that most people could use, you probably won't find them."
    echo ""
    echo "This can sometimes happen if you've installed global node modules"
    echo "under a different node environment (for example, using nvm or nave)."
    echo "It might help to run: "
    echo "history | grep 'npm install' and look for either -g or --global"
    echo ""
    echo "If you aren't really sure, or you are sure and don't care, "
    echo "you can continue; we'll re-install things the proper way, and"
    echo "the next time you run this script you'll see a list of "
    echo "any global node modules you've installed since now."
  fi
  confirm
fi

if (( $USE_NVM )); then
  # NVM will think it is still installed if NVM_DIR is still set
  unset NVM_DIR
  sudo rm -rf $HOME/.nvm
elif (( $USE_NAVE )); then
  sudo rm -rf $HOME/.nave
else
  echo >&2 "error: Unsupported version control system"
  exit 1
fi

# erase all local install paths
DIRECTORIES=("local" "lib" "include" "node*" "npm" ".npm" ".node-gyp")
for i in "${DIRECTORIES[@]}"
do
   if [ -d $HOME/$i ]; then
     LEN=$(ls -A $HOME/$i | wc -l 2> /dev/null)
     if [[ $LEN -gt 1 ]]; then
       echo "${HOME}/${i} has files or directories in it. You should check to see if you need the files in ${HOME}/${i} before proceeding!"
       confirm
     fi
   fi
   # do whatever on $i
done

rm -rf $HOME/{local,lib,include,node*,npm,.npm*,.node-gyp}

# erase globally installed node paths
sudo rm -rf $PREFIX/lib/node*
sudo rm -rf $PREFIX/include/node*
sudo rm -rf $PREFIX/bin/{node,npm}
sudo rm -rf $PREFIX/share/man/man1/node.1
sudo rm -rf $PREFIX/lib/dtrace/node.d

if (( $USE_NVM )); then
  # go home and install NVM just because I feel safe there
  cd $HOME
  # get the latest stable version number of nvm from the repo's homepage
  [ "$STABLE" == "" ] && STABLE=$(curl -s -k https://github.com/creationix/nvm/ | grep "curl https://raw.githubusercontent.com/creationix/nvm/" | grep -oE "v\d+\.\d+\.\d+")
  [[ $STABLE =~ ^v[0-9]+.[0-9]+.[0-9]+$ ]] || STABLE="v0.25.1"
  curl -sL https://raw.githubusercontent.com/creationix/nvm/$STABLE/install.sh | bash
  source $HOME/.nvm/nvm.sh
elif (( $USE_NAVE )); then
  curl -sL https://raw.githubusercontent.com/isaacs/nave/master/nave.sh -o $PREFIX/bin/nave
fi


if (( $USE_NVM )); then
  # install the specified version of node then set it as the default
  nvm install $NODE_VERSION
  nvm alias default $NODE_VERSION
elif (( $USE_NAVE )); then
  nave usemain $NODE_VERSION
fi

if [[ ! -z ${GLOBAL_MODULES// } ]]; then
  echo "Reinstalling your global npm modules:"
  echo $GLOBAL_MODULES
  if [[ $FORCE == 0 ]]; then
    echo "Continue?"
    select yn in "Yes" "No"; do
      case $yn in
        Yes ) npm install --global $GLOBAL_MODULES; break;;
        No ) exit;;
      esac
    done
  else
    npm install --global $GLOBAL_MODULES
  fi

fi

if [[ $OSTYPE =~ "darwin" ]]; then
  echo "node-reinstall is done. 👍"
else
  echo "node-reinstall is done."
fi

echo "You must restart your terminal for changes to take effect."
